package com.sj.common.exception;

import cn.hutool.core.util.StrUtil;
import com.sj.common.resultVo.RV;
import com.sj.common.resultVo.ResultVo;
import com.sj.common.utils.ValidateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@ControllerAdvice
public class TipControllerAdvice {

    /**
     * 全局异常处理
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public ResultVo handler(Exception e) {
        //default error message
//        String msg = "系统内部出错";
//        log.error(msg, e);
        return RV.fail(e.getMessage());
    }


    /**
     * 参数校验异常异常处理
     */
    @ResponseBody
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ResultVo handlerConstraintViolationException(Exception e) {
        ConstraintViolationException constraintViolationException = (ConstraintViolationException) e;
        String msg = StringUtils.collectionToCommaDelimitedString(
                constraintViolationException.getConstraintViolations()
                        .stream()
                        .map(ConstraintViolation::getMessage)
                        .collect(Collectors.toList()));
        return RV.fail(msg);
//        return RV.fail(msg);
    }


    @ResponseBody
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResultVo handlerMethodArgumentNotValidException(Exception e) {
        StringBuilder message = new StringBuilder();
        MethodArgumentNotValidException exception = (MethodArgumentNotValidException) e;
        List<ObjectError> errors = exception.getBindingResult().getAllErrors();
        for (ObjectError objectError : errors) {
            if (objectError instanceof FieldError) {
                FieldError fieldError = (FieldError) objectError;
                message.append(StrUtil.toUnderlineCase(fieldError.getField())).append(":").append(fieldError.getDefaultMessage()).append(",");
            } else {
                message.append(objectError.getDefaultMessage()).append(",");
            }

        }
        return RV.fail(message.toString());
    }

    @ResponseBody
    @ExceptionHandler(value = BindException.class)
    public ResultVo handlerBindException(Exception e) {
        BindException bindException = (BindException) e;
        String msg = StringUtils.collectionToCommaDelimitedString(
                bindException.getAllErrors()
                        .stream()
                        .map(DefaultMessageSourceResolvable::getDefaultMessage)
                        .collect(Collectors.toList()));
        return RV.fail(msg);
    }

    @ResponseBody
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public ResultVo handlerMissingServletRequestParameterException(Exception e) {
        return RV.fail("缺少必填参数");
    }

    @ResponseBody
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public ResultVo handlerHttpMessageNotReadableException(Exception e) {
        return RV.fail(e.getMessage());
    }

/*
    @ResponseBody
    @ExceptionHandler(value = ParamErrorException.class)
    public ResultVo handlerParamError(Exception e) {
        if (ValidateUtil.isEmpty(e.getMessage())) {
            return RV.fail("参数错误");
        } else {
            return RV.fail(e.getMessage());
        }
    }
*/

    @ResponseBody
    @ExceptionHandler(value = MbsException.class)
    public ResultVo handlerTip(Exception e) {
        return RV.fail(e.getMessage());
    }

}
